import pandas as pd
# Import the wrapper objects for model interaction.
from examples.example_10_advanced_ciw.ex_10_ciw_model import N
from vidigi.ciw import event_log_from_ciw_recs
from vidigi.utils import EventPosition, create_event_position_df
from vidigi.animation import animate_activity_log
import plotly.io as pio
pio.renderers.default = "notebook"
import os
import ciwA More Complex Ciw Example with Backgrounds
View Imported Code for the ciw model
import ciw
# From https://ciw.readthedocs.io/en/latest/Tutorial/tutorial_ii.html
N = ciw.create_network(
arrival_distributions=[ciw.dists.Exponential(rate=0.3 / 60),
ciw.dists.Exponential(rate=0.2 / 60),
None],
service_distributions=[ciw.dists.Exponential(rate=2.0 / 60),
ciw.dists.Exponential(rate=1.4 / 60),
ciw.dists.Exponential(rate=1.0 / 60)],
routing=[[0.0, 0.3, 0.7],
[0.0, 0.0, 1.0],
[0.0, 0.0, 0.0]],
number_of_servers=[1, 2, 2]
)ciw.seed(42)
Q = ciw.Simulation(N)
RESULTS_COLLECTION_PERIOD = 180 * 60 # 180 minutes x 60 seconds
Q.simulate_until_max_time(RESULTS_COLLECTION_PERIOD)
recs = Q.get_all_records()
pd.DataFrame(recs).sort_values(['id_number', 'service_start_date']).head(20)| id_number | customer_class | original_customer_class | node | arrival_date | waiting_time | service_start_date | service_time | service_end_date | time_blocked | exit_date | destination | queue_size_at_arrival | queue_size_at_departure | server_id | record_type | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | Customer | Customer | 2 | 7.598652 | 0.000000 | 7.598652 | 13.783888 | 21.382540 | 0.0 | 21.382540 | 3 | 0 | 0 | 1 | service |
| 1 | 1 | Customer | Customer | 3 | 21.382540 | 0.000000 | 21.382540 | 67.750381 | 89.132921 | 0.0 | 89.132921 | -1 | 0 | 0 | 1 | service |
| 6 | 2 | Customer | Customer | 2 | 83.374507 | 0.000000 | 83.374507 | 95.455204 | 178.829712 | 0.0 | 178.829712 | 3 | 0 | 0 | 1 | service |
| 7 | 2 | Customer | Customer | 3 | 178.829712 | 0.000000 | 178.829712 | 53.388522 | 232.218234 | 0.0 | 232.218234 | -1 | 1 | 1 | 1 | service |
| 2 | 3 | Customer | Customer | 2 | 110.660229 | 0.000000 | 110.660229 | 23.487693 | 134.147921 | 0.0 | 134.147921 | 3 | 1 | 2 | 2 | service |
| 3 | 3 | Customer | Customer | 3 | 134.147921 | 0.000000 | 134.147921 | 13.301500 | 147.449421 | 0.0 | 147.449421 | -1 | 0 | 1 | 1 | service |
| 4 | 4 | Customer | Customer | 2 | 119.735282 | 14.412639 | 134.147921 | 1.152617 | 135.300539 | 0.0 | 135.300539 | 3 | 2 | 1 | 2 | service |
| 5 | 4 | Customer | Customer | 3 | 135.300539 | 0.000000 | 135.300539 | 47.239755 | 182.540294 | 0.0 | 182.540294 | -1 | 1 | 1 | 2 | service |
| 16 | 5 | Customer | Customer | 2 | 193.750291 | 0.000000 | 193.750291 | 71.045918 | 264.796209 | 0.0 | 264.796209 | 3 | 0 | 1 | 1 | service |
| 17 | 5 | Customer | Customer | 3 | 264.796209 | 0.000000 | 264.796209 | 216.972911 | 481.769120 | 0.0 | 481.769120 | -1 | 1 | 0 | 2 | service |
| 12 | 6 | Customer | Customer | 2 | 195.706281 | 0.000000 | 195.706281 | 70.241394 | 265.947675 | 0.0 | 265.947675 | 3 | 1 | 0 | 2 | service |
| 13 | 6 | Customer | Customer | 3 | 265.947675 | 30.320583 | 296.268259 | 48.183165 | 344.451423 | 0.0 | 344.451423 | -1 | 2 | 2 | 1 | service |
| 8 | 7 | Customer | Customer | 1 | 204.012057 | 0.000000 | 204.012057 | 12.476853 | 216.488910 | 0.0 | 216.488910 | 3 | 0 | 0 | 1 | service |
| 9 | 7 | Customer | Customer | 3 | 216.488910 | 0.000000 | 216.488910 | 24.622136 | 241.111046 | 0.0 | 241.111046 | -1 | 1 | 1 | 2 | service |
| 10 | 8 | Customer | Customer | 1 | 237.809311 | 0.000000 | 237.809311 | 2.919980 | 240.729291 | 0.0 | 240.729291 | 3 | 0 | 0 | 1 | service |
| 11 | 8 | Customer | Customer | 3 | 240.729291 | 0.000000 | 240.729291 | 55.538968 | 296.268259 | 0.0 | 296.268259 | -1 | 1 | 2 | 1 | service |
| 14 | 9 | Customer | Customer | 1 | 258.153048 | 0.000000 | 258.153048 | 49.371898 | 307.524946 | 0.0 | 307.524946 | 3 | 0 | 0 | 1 | service |
| 15 | 9 | Customer | Customer | 3 | 307.524946 | 36.926477 | 344.451423 | 57.821772 | 402.273196 | 0.0 | 402.273196 | -1 | 2 | 1 | 1 | service |
| 20 | 10 | Customer | Customer | 1 | 519.821134 | 0.000000 | 519.821134 | 59.351398 | 579.172532 | 0.0 | 579.172532 | 2 | 0 | 0 | 1 | service |
| 21 | 10 | Customer | Customer | 2 | 579.172532 | 1.027521 | 580.200053 | 4.563164 | 584.763217 | 0.0 | 584.763217 | 3 | 2 | 1 | 2 | service |
event_log = event_log_from_ciw_recs(
recs,
node_name_list=["cold_food", "hot_food", "till"]
)
event_log[event_log["entity_id"]==13]| entity_id | pathway | event_type | event | time | resource_id | |
|---|---|---|---|---|---|---|
| 99 | 13 | Model | arrival_departure | arrival | 671.604123 | NaN |
| 100 | 13 | Model | queue | hot_food_wait_begins | 671.604123 | NaN |
| 101 | 13 | Model | resource_use | hot_food_begins | 671.604123 | 1.0 |
| 102 | 13 | Model | resource_use_end | hot_food_ends | 684.914665 | 1.0 |
| 103 | 13 | Model | queue | till_wait_begins | 684.914665 | NaN |
| 104 | 13 | Model | resource_use | till_begins | 684.914665 | 1.0 |
| 105 | 13 | Model | resource_use_end | till_ends | 741.277635 | 1.0 |
| 106 | 13 | Model | arrival_departure | depart | 741.277635 | NaN |
# Create a suitable class to pass in the resource numbers to the animation function
class model_params():
def __init__(self):
self.cold_food_servers = 1
self.hot_food_servers = 2
self.tills = 2
params = model_params()# # Create required event_position_df for vidigi animation
# event_position_df = pd.DataFrame([
# {'event': 'arrival',
# 'x': 30, 'y': 550,
# 'label': "Arrival"},
# {'event': 'cold_food_wait_begins',
# 'x': 200, 'y': 510,
# 'label': "Waiting for Cold Food"},
# {'event': 'cold_food_begins',
# 'x': 210, 'y': 370,
# 'resource':'cold_food_servers',
# 'label': "Being Served Cold Food"},
# {'event': 'hot_food_wait_begins',
# 'x': 505, 'y': 510,
# 'label': "Waiting for Hot Food"},
# {'event': 'hot_food_begins',
# 'x': 505, 'y': 370,
# 'resource':'hot_food_servers',
# 'label': "Being Served Hot Food"},
# {'event': 'till_wait_begins',
# 'x': 350, 'y': 170,
# 'label': "Waiting for Till"},
# {'event': 'till_begins',
# 'x': 350, 'y': 120,
# 'resource':'tills',
# 'label': "Being Served at Till"},
# {'event': 'depart',
# 'x': 600, 'y': 10,
# 'label': "Exit"}
# ])
# event_position_df
event_position_df = create_event_position_df( [
EventPosition(event='arrival', x=30, y=550, label="Arrival"),
EventPosition(event='cold_food_wait_begins', x=200, y=510, label="Waiting for Cold Food"),
EventPosition(event='cold_food_begins', x=210, y=370, resource='cold_food_servers', label="Being Served Cold Food"),
EventPosition(event='hot_food_wait_begins', x=505, y=510, label="Waiting for Hot Food"),
EventPosition(event='hot_food_begins', x=505, y=370, resource='hot_food_servers', label="Being Served Hot Food"),
EventPosition(event='till_wait_begins', x=350, y=170, label="Waiting for Till"),
EventPosition(event='till_begins', x=350, y=120, resource='tills', label="Being Served at Till"),
EventPosition(event='depart', x=600, y=10, label="Exit")
]
)# Create animation
params = model_params()
animate_activity_log(
event_log=event_log,
event_position_df=event_position_df,
scenario=model_params(),
simulation_time_unit="seconds",
time_display_units="dhms",
debug_mode=True,
setup_mode=False,
every_x_time_units=5, # 20 seconds
include_play_button=True,
entity_icon_size=20,
gap_between_entities=15,
gap_between_queue_rows=25,
gap_between_resources=30,
plotly_height=525,
frame_duration=200,
frame_transition_duration=600,
plotly_width=900,
override_x_max=700,
override_y_max=600,
limit_duration=RESULTS_COLLECTION_PERIOD,
wrap_queues_at=25,
wrap_resources_at=50,
step_snapshot_max=75,
start_time="12:00:00",
text_size=20,
display_stage_labels=False,
add_background_image="cafe_floorplan.drawio (1).png"
)Animation function called at 11:30:43
Iteration through time-unit-by-time-unit logs complete 11:30:47
Snapshot df concatenation complete at 11:30:47
Reshaped animation dataframe finished construction at 11:30:48
Placement dataframe finished construction at 11:30:48
Output animation generation complete at 11:30:55
Total Time Elapsed: 12.58 seconds